package com.kobeliu.controller;

import com.google.gson.Gson;
import com.kobeliu.api.feign.UsersMicroServiceFeign;
import com.kobeliu.api.interceptor.JwtCurrentUserInterceptor;
import com.kobeliu.base.BaseInfoProperties;
import com.kobeliu.enums.CompanyReviewStatus;
import com.kobeliu.exceptions.GraceException;
import com.kobeliu.pojo.Company;
import com.kobeliu.pojo.Users;
import com.kobeliu.pojo.bo.*;
import com.kobeliu.pojo.vo.CompanyInfoVO;
import com.kobeliu.pojo.vo.CompanySimpleVO;
import com.kobeliu.pojo.vo.UsersVO;
import com.kobeliu.result.GraceJSONResult;
import com.kobeliu.result.ResponseStatusEnum;
import com.kobeliu.service.CompanyPhotoService;
import com.kobeliu.service.CompanyService;
import com.kobeliu.utils.PagedGridResult;
import com.tencentcloudapi.btoe.v20210303.models.CreateVideoDepositRequest;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

@RestController
@RequestMapping("company")
@Slf4j
public class CompanyController extends BaseInfoProperties {

    @Autowired
    private CompanyService companyService;

    @Autowired
    private UsersMicroServiceFeign usersMicroServiceFeign;

    @Autowired
    private CompanyPhotoService companyPhotoService;

    /**
     * 根据全名查询公司是否在公司存在
     * @param fullName
     * @return
     */
    @PostMapping("getByFullName")
    public GraceJSONResult getByFullName(String fullName){

        if(StringUtils.isBlank(fullName)){
            return GraceJSONResult.error();
        }

        Company company = companyService.getByFullName(fullName);

        if(company==null) return GraceJSONResult.ok(null);

        CompanySimpleVO companySimpleVO = new CompanySimpleVO();
        BeanUtils.copyProperties(company,companySimpleVO);

        return GraceJSONResult.ok(companySimpleVO);
    }

    /**
     * 创建新company申请
     * @param createCompanyBO
     * @return
     */
    @PostMapping("createNewCompany")
    public GraceJSONResult createNewCompany(@RequestBody @Valid CreateCompanyBO createCompanyBO){

        //校验
        if(createCompanyBO==null)
            return GraceJSONResult.errorCustom(ResponseStatusEnum.COMPANY_INFO_UPDATED_ERROR);
//        if(companyService.getByFullName(createCompanyBO.getCompanyName())!=null)
//            return GraceJSONResult.errorMsg("该公司已存在");

        return GraceJSONResult.ok(companyService.createNewCompany(createCompanyBO));
    }

    /**
     * 重新申请 驳回 --》 未审核
     * @param createCompanyBO
     * @return
     */
    @PostMapping("resetCompany")
    public GraceJSONResult resetCompany(@RequestBody @Valid CreateCompanyBO createCompanyBO){

        //校验
        if(createCompanyBO==null)
            return GraceJSONResult.errorCustom(ResponseStatusEnum.COMPANY_INFO_UPDATED_ERROR);

        return GraceJSONResult.ok(companyService.resetNewCompany(createCompanyBO));

    }

    /**
     * 根据companyId查询company信息 以及 若flag为true，则查询关联的hr的数量
     * @param companyId
     * @param withHRCount
     * @return
     */
    @PostMapping("getInfo")
    public GraceJSONResult getInfo(@RequestParam("companyId") String companyId,
                                        @RequestParam("withHRCounts") Boolean withHRCount){

        CompanySimpleVO simpleVO = new CompanySimpleVO();
        if(companyId!=null){
            simpleVO = getCompany(companyId);
            if(withHRCount) {
                Long HRCount = companyService.getCountByCompanyId(companyId);
                simpleVO.setHrCounts(HRCount);
            }
        }

        return GraceJSONResult.ok(simpleVO);
    }


    private CompanySimpleVO getCompany(String companyId){
        if(StringUtils.isBlank(companyId))
            return null;

        String companyJson = redis.get(REDIS_COMPANY_BASE_INFO + ":" + companyId);
        if(companyJson!=null){
            return new Gson().fromJson(companyJson,CompanySimpleVO.class);
        }else{

            //查询db
            Company company = companyService.getByCompanyId(companyId);
            if(company==null)
                return null;
            CompanySimpleVO companySimpleVO = new CompanySimpleVO();
            BeanUtils.copyProperties(company,companySimpleVO);

            //存入redis
            redis.set(REDIS_COMPANY_BASE_INFO + ":" + companyId,new Gson().toJson(companySimpleVO),5*60);

            return companySimpleVO;
        }
    }

    /**
     * 根据userID和companyID绑定关系
     * @param bo
     * @return
     */
    @PostMapping("goReviewCompany")
    @GlobalTransactional
    public GraceJSONResult getInfo(@RequestBody ReviewCompanyBO bo){

        //1.微服务调用，绑定HR企业Id
        GraceJSONResult graceJSONResult = usersMicroServiceFeign.bindingHRToCompany(bo.getHrUserId(),bo.getRealName(),bo.getCompanyId());
        String hrMobile = graceJSONResult.getData().toString();

        //2.保存审核，修改状态为审核中3
        bo.setHrMobile(hrMobile);
        companyService.commitReviewCompanyInfo(bo);

        //删除缓存
        redis.del(REDIS_COMPANY_BASE_INFO+":"+bo.getCompanyId());
        redis.del(REDIS_COMPANY_MORE_INFO+":"+bo.getCompanyId());

        return GraceJSONResult.ok();

    }

    /**
     * 跟据hr的userId查询企业的最新企业信息
     * @param hrUserId
     * @return
     */
    @PostMapping("information")
    public GraceJSONResult information(String hrUserId){
        Long start = System.currentTimeMillis();

        UsersVO hrInfoVO = getHRInfoVO(hrUserId);

        CompanySimpleVO company = getCompany(hrInfoVO.getHrInWhichCompanyId());
        if(company == null){
            company = new CompanySimpleVO();
            company.setReviewStatus(0);
        }

        log.info("===========================================");
        log.info("information消耗的时长为=="+(System.currentTimeMillis()-start)+"ms");
        log.info("===========================================");


        return GraceJSONResult.ok(company);
    }


    private UsersVO getHRInfoVO(String userId){

        GraceJSONResult graceJSONResult = usersMicroServiceFeign.getInfo(userId);
        String json = graceJSONResult.getData().toString();
        UsersVO vo = new Gson().fromJson(json,UsersVO.class);
        return vo;

    }

    /**
     * 根据
     * @param companyBO
     * @param page
     * @param limit
     * @return
     */
    @PostMapping("admin/getCompanyList")
    public GraceJSONResult adminGetCompanyList(@RequestBody @Valid QueryCompanyBO companyBO,
                                                    Integer page,Integer limit){

        if(page==null) page=1;
        if(limit==null) limit=10;

        PagedGridResult pagedGridResult = companyService.queryCompanyListPaged(companyBO,page,limit);
        return GraceJSONResult.ok(pagedGridResult);

    }

    /**
     * 根据企业ID获取最新企业数据
     * @param companyId
     * @return
     */
    @PostMapping("admin/getCompanyInfo")
    public GraceJSONResult getCompanyInfo(String companyId){

        return GraceJSONResult.ok(companyService.getCompanyInfoVO(companyId));
    }


    /**
     * 企业审核通过，用户成为HR角色
     * @param bo
     * @return
     */
    @GlobalTransactional
    @PostMapping("admin/doReview")
    public GraceJSONResult doReview(@RequestBody @Valid ReviewCompanyBO bo){

        //1.审核企业
        companyService.updateReviewInfo(bo);
        //2.如果审核成功，则更新用户角色为HR
        if(Objects.equals(bo.getReviewStatus(), CompanyReviewStatus.SUCCESSFUL.type)){
            //用户修改成为hr
            usersMicroServiceFeign.changUser2Hr(bo.getHrUserId());
            //更新Es中的数据
            companyService.updateAggsUserInfo(bo);
        }
        //3.清除用户端的企业缓存
        redis.del(REDIS_COMPANY_BASE_INFO+":"+bo.getCompanyId());

        return GraceJSONResult.ok();
    }

    /**
     * 更新审核后的信息
     * @param bo
     */
    private void updateReviewInfo(ReviewCompanyBO bo){
        companyService.updateReviewInfo(bo);

    }

    // *********************SAAS企业端使用 START***********************

    /**
     * saas端获得企业基础信息
     * @return
     */
    @PostMapping("info")
    public GraceJSONResult info(){

        //携带token 故在interceptor层已经拿到了对应的基础user信息
        Users users = JwtCurrentUserInterceptor.currentUser.get();
        CompanySimpleVO company = getCompany(users.getHrInWhichCompanyId());
        return GraceJSONResult.ok(company);

    }

    /**
     * saas获取企业详情
     * @return
     */
    @PostMapping("saas/moreInfo")
    public GraceJSONResult saasMoreInfo(){

        Users users = JwtCurrentUserInterceptor.currentUser.get();

        CompanyInfoVO companyMoreInfo = getCompanyMoreInfo(users.getHrInWhichCompanyId());

        return GraceJSONResult.ok(companyMoreInfo);
    }


    private CompanyInfoVO getCompanyMoreInfo(String companyId){
        if(StringUtils.isBlank(companyId))
            return null;

        String moreInfoJson = redis.get(REDIS_COMPANY_MORE_INFO + ":" + companyId);
        if(moreInfoJson!=null){
            return new Gson().fromJson(moreInfoJson,CompanyInfoVO.class);
        }else{

            //查询db
            Company company = companyService.getByCompanyId(companyId);
            if(company==null)
                return null;
            CompanyInfoVO companyInfoVO = new CompanyInfoVO();
            BeanUtils.copyProperties(company,companyInfoVO);

            //存入redis
            redis.set(REDIS_COMPANY_MORE_INFO + ":" + companyId,new Gson().toJson(companyInfoVO),5*60);

            return companyInfoVO;
        }
    }

    // *********************SAAS企业端使用 END*************************


    // *********************app端使用 START*************************

    /**
     * app端获取企业的详情
     * @param companyId
     * @return
     */
    @PostMapping("/moreInfo")
    public GraceJSONResult moreInfo(String companyId){

//        Users users = JwtCurrentUserInterceptor.currentUser.get();

        CompanyInfoVO companyMoreInfo = getCompanyMoreInfo(companyId);

        return GraceJSONResult.ok(companyMoreInfo);
    }

    @Autowired
    private RedissonClient redissonClient;

    @PostMapping("/modify")
    public GraceJSONResult modify(@RequestBody ModifyCompanyInfoBO infoBO){

        // 判断当前用户绑定的用户与修改的企业是否一致
        checkUser(infoBO.getCurrentUserId(),infoBO.getCompanyId());

        //获得锁
        String lockName = "redisson-lock";
        RLock rLock = redissonClient.getLock(lockName);

        //可重入锁 --》 当前线程可以重复进入同一把锁，但是要释放n遍

        //加锁
        rLock.lock();
        try{
            //校验通过，修改信息
            companyService.updateCompanyInfo(infoBO);
        }finally {
            //解锁
            rLock.unlock();
        }


        //company表中不包含photos 所以photos另外处理 放入CompanyPhoto表中

        if(StringUtils.isNotBlank(infoBO.getPhotos())){
            companyPhotoService.insertOrModify(infoBO);
        }

        return GraceJSONResult.ok();
    }

    /**
     * 判断当前用户绑定的用户与修改的企业是否一致
     * @param currentUserId
     * @param companyId
     */
    private void checkUser(String currentUserId,String companyId){

        if(StringUtils.isBlank(currentUserId)){
            GraceException.display(ResponseStatusEnum.COMPANY_INFO_UPDATED_ERROR);
        }

        //根据用户获取信息
        UsersVO hrUser = getHRInfoVO(currentUserId);
        if(hrUser!=null && !hrUser.getHrInWhichCompanyId().equalsIgnoreCase(companyId)){
            GraceException.display(ResponseStatusEnum.COMPANY_INFO_UPDATED_NO_AUTH_ERROR);
        }

    }

    /**
     * 根据companyId获取photos
     * @param companyId
     * @return
     */
    @PostMapping("/getPhotos")
    public GraceJSONResult getPhotos(@RequestParam("companyId")String companyId){

        if(StringUtils.isBlank(companyId))
            return GraceJSONResult.errorCustom(ResponseStatusEnum.COMPANY_INFO_UPDATED_ERROR);

        String photosStr = companyPhotoService.getPhotos(companyId);

        return GraceJSONResult.ok(photosStr);
    }


    // *********************app端使用 END***************************


    @PostMapping("getCompanyInfos")
    GraceJSONResult getCompanyInfos(@RequestBody SearchBO search){

        return GraceJSONResult.ok(new Gson().toJson(companyService.getList(search.getCompanyIds())));
//        return GraceJSONResult.ok(companyService.getList(search.getCompanyIds()));
    }

}
